using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
using Avalonia.Controls.Notifications;

namespace Avalonia.Exusiai.Editor.Models;

public class Node:INotifyPropertyChanged
{
    private string _name;
    public string Name
    {
        get => _name;
        set
        {
            if (_name==value) return;
            _name = value; OnPropertyChanged(nameof(Name)); }}
    public bool IsFile { get; set; }
    public string Path { get; set; }
    public ObservableCollection<Node>? Children { get; set; }
    public Node(string path)
    {
        Name = System.IO.Path.GetFileName(path);
        IsFile = false;
        Path = System.IO.Path.GetFullPath(path);
        Children = new ObservableCollection<Node>();
    }

    public event PropertyChangedEventHandler? PropertyChanged;

    private void OnPropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
    public void AddChild(Node child)
    {
        Children.Add(child);
    }

    public void LoadChildren()
    {
        if (IsFile || Children.Count > 0)
            return;

        try
        {
            // Add subdirectories
            string[] subdirectories = Directory.GetDirectories(Path);
            foreach (string subdir in subdirectories)
            {
                AddChild(new Node(subdir));
            }

            // Add files
            string[] files = Directory.GetFiles(Path);
            foreach (string file in files)
            {
                AddChild(new Node(file) { IsFile = true });
            }
        }
        catch (UnauthorizedAccessException e)
        {
            Console.WriteLine($"Unauthorized Access: {e.Message}");
        }
        catch (DirectoryNotFoundException e)
        {
            Console.WriteLine($"Directory Not Found: {e.Message}");
        }
        catch (IOException e)
        {
            Console.WriteLine($"IO Exception: {e.Message}");
        }
        catch (Exception e)
        {
            Console.WriteLine($"Exception: {e.Message}");
        }
    }

    #region Static Methods

    public static void RenameNode(Node selectedItem, string newName)
    {
        selectedItem.Name = newName;
        selectedItem.Path = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(selectedItem.Path) ?? string.Empty, newName);
    }

    public static void PopulateTree(string path, ObservableCollection<Node> tree)
    {
        var node = new Node(path);
        tree.Add(node);
    }

    public static void RemoveNodeRecursively(ObservableCollection<Node> root,Node selectedItem)
    {
        if (root.Contains(selectedItem))
        {
            root.Remove(selectedItem);
        }else
        {
            foreach (Node item in root)
            {
                if (item.Children!=null)
                {
                    RemoveNodeRecursively(item.Children, selectedItem);
                }
            }
        }
    }
    public static void NewFolder(Node selectedItem)
    {
        string newFolderPath = System.IO.Path.Combine(selectedItem.Path, "New Folder");

        if (Directory.Exists(newFolderPath))
            return;

        try
        {
            Directory.CreateDirectory(newFolderPath);
            selectedItem.AddChild(new Node(newFolderPath));
        }
        catch (UnauthorizedAccessException e)
        {
            Console.WriteLine($"Unauthorized Access: {e.Message}");
        }
        catch (IOException e)
        {
            Console.WriteLine($"IO Exception: {e.Message}");
        }
        catch (Exception e)
        {
            Console.WriteLine($"Exception: {e.Message}");
        }
    }

    public static void NewFile(Node selectedItem)
    {
        string newFilePath = System.IO.Path.Combine(selectedItem.Path, "New File.cs");

        if (File.Exists(newFilePath))
            return;

        try
        {
            File.Create(newFilePath).Close(); // Ensure the file handle is closed
            selectedItem.AddChild(new Node(newFilePath) { IsFile = true });
        }
        catch (UnauthorizedAccessException e)
        {
            Console.WriteLine($"Unauthorized Access: {e.Message}");
        }
        catch (IOException e)
        {
            Console.WriteLine($"IO Exception: {e.Message}");
        }
        catch (Exception e)
        {
            Console.WriteLine($"Exception: {e.Message}");
        }
    }
    #endregion
}